1 module hip.net.backend.websocket; 2 import hip.wasm; 3 import hip.api.net.hipnet; 4 public import hip.network; 5 6 version(WebAssembly): 7 8 alias WasmWebsocket = size_t; 9 extern(C) WasmWebsocket connectWebsocket( 10 JSStringType url, 11 JSDelegateType!(void delegate()) onConnected, 12 JSDelegateType!(void delegate()) onClose, 13 JSDelegateType!(void delegate(size_t id)) onFirstMessage 14 ); 15 extern(C) void closeWebsocket(WasmWebsocket); 16 extern(C) void websocketSendData(WasmWebsocket, uint from, uint to, size_t length, ubyte* dataPtr); 17 extern(C) ubyte* websocketGetData(WasmWebsocket); 18 19 20 /** 21 * Specification: 22 * - The first message received by a Hipreme Engine websocket must always be its own connection ID. 23 */ 24 class WASMWebsocketNetwork : INetworkBackend 25 { 26 WasmWebsocket socket; 27 NetConnectStatus _status; 28 uint socketID = NetID.server; //That is same as invalid since a socket can't be the server. 29 uint connectedTo = NetID.server; 30 void delegate() onConnect; 31 32 33 ///Buffer used if programmer tried to send data before assigning to its socket id 34 private ubyte[][] scheduledDataSend; 35 36 bool isHost() const { return false; } 37 38 NetConnectStatus connect(NetIPAddress ip, void delegate() onConnect, size_t id = NetID.server) 39 { 40 import hip.util.string; 41 if(_status == NetConnectStatus.waiting) 42 return _status; 43 this.onConnect = onConnect; 44 connectedTo = id; 45 String s; 46 if(!ip.ip.startsWith("ws://")) 47 s = String("ws://", ip.ip); 48 else 49 s = String(ip.ip); 50 51 if(ip.port != 0) 52 s = String(s, ":", ip.port, "/ws"); 53 54 socket = connectWebsocket( 55 JSString(s.toString).tupleof, 56 sendJSDelegate!(() 57 { 58 this._status = NetConnectStatus.connected; 59 }).tupleof, 60 sendJSDelegate!(() 61 { 62 this._status = NetConnectStatus.disconnected; 63 }).tupleof, 64 sendJSDelegate!((size_t id) 65 { 66 import hip.console.log; 67 socketID = id; 68 this.onConnect(); 69 logln("Connection Established. Socket ID: ", id, " connected to ", connectedTo); 70 foreach(data; scheduledDataSend) 71 websocketSendData(socket, socketID, connectedTo, data.length, data.ptr); 72 scheduledDataSend = null; 73 }).tupleof 74 ); 75 76 return _status = NetConnectStatus.waiting; 77 } 78 79 void targetConnectionID(size_t id) 80 { 81 connectedTo = id; 82 if(socketID != NetID.server && connectedTo == socketID) 83 { 84 import hip.util.string; 85 throw new Exception(SmallString("Tried to connect socket ", connectedTo, " to its same ID.").toString); 86 } 87 } 88 size_t getConnectionSelfID() const { return socketID; } 89 size_t targetConnectionID() const { return connectedTo; } 90 91 bool sendData(ubyte[] data) 92 { 93 if(socketID < NetID.start) 94 scheduledDataSend~= data; 95 else 96 websocketSendData(socket, socketID, connectedTo, data.length, data.ptr); 97 return true; 98 } 99 100 uint getData(ref ubyte[] tempBuffer) 101 { 102 tempBuffer = getWasmArray(websocketGetData(socket)); 103 return tempBuffer.length; 104 } 105 106 void disconnect() 107 { 108 if(socket != 0) 109 { 110 closeWebsocket(socket); 111 socket = 0; 112 } 113 } 114 115 void attemptReconnection() 116 { 117 118 } 119 120 NetConnectStatus status() const { return _status; } 121 }